﻿using System;
using System.IO;
using System.Runtime.CompilerServices;

namespace MLSharp.Utilities
{
	/// <summary>
	/// Provides a simple tool for writing data to a CSV file.
	/// </summary>
	public class CsvWriter : IDisposable
	{
		#region Private Fields

		/// <summary>
		/// Used to write to the actual file.
		/// </summary>
		private StreamWriter mWriter;

		#endregion

		#region Public Constructors

		/// <summary>
		/// Creates a writer that will use the specified output file. 
		/// If the file exists, it is truncated.
		/// </summary>
		/// <param name="outputFile"></param>
		public CsvWriter(string outputFile)
		{
			mWriter = new StreamWriter(outputFile, false);
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// Appends the specified values as a new row in the file.
		/// </summary>
		/// <param name="values">The values to write.</param>
		[MethodImpl(MethodImplOptions.Synchronized)]
		public void WriteRow(params object[] values)
		{
			if (values == null || values.Length == 0)
			{
				mWriter.WriteLine();
				return;
			}

			string[] formattedValues = new string[values.Length];

			for (int i=0; i < values.Length; i++)
			{
				formattedValues[i] = values[i] != null ? values[i].ToString() : String.Empty;

				bool containsQuotes = formattedValues[i].Contains("\"");
				bool containsCommas = formattedValues[i].Contains(",");

				//If it contains quotes escape them
				if (containsQuotes)
				{
					formattedValues[i] = formattedValues[i].Replace("\"", "\"\"");
				}

				//If it contains commas or quotes, it has to be enclosed in quotes.
				if (containsCommas || containsQuotes)
				{
					formattedValues[i] = string.Format("\"{0}\"", formattedValues[i]);
				}
			}

			mWriter.WriteLine(string.Join(",", formattedValues));
		}

		#endregion

		#region IDisposable-Related Members

		/// <summary>
		/// Disposes the underlying stream if it is still open.
		/// </summary>
		public void Dispose()
		{
			if (mWriter != null)
			{
				mWriter.Close();
				mWriter = null;
			}

			GC.SuppressFinalize(this);
		}

		/// <summary>
		/// Calls the Dispose method.
		/// </summary>
		~CsvWriter()
		{
			Dispose();
		}

		#endregion
	}
}